/* #####################################################################
 * # Materia : Analisis Comparativo de Lenguajes                       #
 * # Ejercicio : Dados 2 matrices devolver la matriz resultante de     #
 * #             multiplicar dichas matrices. Utilice unicamente       #
 * #             punteros para recorrer las matrices dadas.            #
 * #                                                                   #
 * # Profesores a Cargo: Marta Novaira Franco Brusatti Ariel Gonzales. #
 * #                                                                   #
 * # Integrantes: Prone Lucas , Correa Carlos Maximiliano.             #
 * #####################################################################*/

#include<stdio.h>
#include<math.h>
#include<stdlib.h>

/*---------------------------------------------------------------------------------------------------------------------*/

/*Metodo que inicializa el tamaño reservado para las matrices utilizadas.*/
int ** matrizInicializar(int ** mat,int n, int m){
		mat = (int **) malloc( n * sizeof(int *)); /* reserva de espacio para n filas,  de la mat1*/
		int j;
		for ( j = 0 ; j < n; j++){
			mat[j] = (int *) malloc(m * sizeof(int)); /* reserva de espacio de memoria para las m  columnas, de la mat1*/
		}
		return (mat);		
	}


/*---------------------------------------------------------------------------------------------------------------------*/
/*Metodo cargar: Metodo que pide al usuario los elementos de la matriz a cargar.*/
int **  cargar(int ** mat,int n, int m){
	/*Pre: n: Nº filas,  m: Nº columnas */
		int i,j;	
				for (i=0;i<n;i++) { /* Bucle Externo, Recorre Filas*/
					for (j=0;j<m;j++) {/*Bucle Interno, Recorre Columnas*/
						
						printf("A[%i][%i]: ",i,j);
						scanf("%i",&*(*(mat+i)+j));
					
					} /*Fin Bucle Interno*/
				}/*Fin Bucle Externo*/
				return(mat);
	/*Post: matriz [n][m] => n*m elementos*/
	}
	

/*---------------------------------------------------------------------------------------------------------------------*/
/*Metodo Mostrar: Muestra por pantalla las matrices  pasadas como parametros*/
void mostrar(int ** mat,int n, int m) {
	int i,j;
		for (i=0;i<n;i++) { /* Bucle Externo, Recorre Filas*/
			for (j=0;j<m;j++) {/*Bucle Interno, Recorre Columnas*/
				printf(" | %i",*(*(mat+i)+j));
							  }/*Fin Bucle Interno*/
			printf(" | \n");
			}/*Fin Bucle Externo*/
			
		} /*Fin de mostrar*/
	
	
/*---------------------------------------------------------------------------------------------------------------------*/	
/*Metodo ProductoCruz : Metodo que efectua el producto cruz de dos matrices dadas.*/
int** productoCruz(int ** mat1,int ** mat2,int nFil1,int mCol1,int mCol2){	
	/*Pre: mCol1 == nFil2*/
	int** result = matrizInicializar(result,nFil1,mCol2); /*Inicializa la matriz resultado*/
	
	int i,j,aux,k;
	for (i=0; i < nFil1; i++){
		for(j=0; j < mCol2; j++){
			aux = 0;
			for(k=0; k < mCol1 ; k++){
				aux = aux + *(*(mat1+i)+k) * *(*(mat2+k)+j); /*Acumulador*/
				}
			*(*(result+i)+j) = aux; 
			}
		}
		return result;	
	/*Post : result[nFil1][mCol2]*/
	}		
	
	 
/*---------------------------------------------------------------------------------------------------------------------*/
int main(int argc, char *argi[]){ /*INICIO DEL CUERPO DEL PROGRAMA*/

	int ** mat1; /*Matriz dinamica 1*/
	int nFil1, mCol1; /*Numero de filas y columnas de la matriz 1*/

	int ** mat2;/*Matriz dinamica 2 */
	int nFil2, mCol2; /*Numero de filas y columnas de la matriz 2*/
		
	printf( "Ingrese el numero de filas de la Primer Matriz: " );
	scanf("%d", & nFil1);
	printf( "Ingrese el Numero de columnas de la Primer Matriz : " );
	scanf("%d", & mCol1);
	mat1 = matrizInicializar(mat1,nFil1,mCol1);
	printf( "Carga de los elementos de la Primer Matriz : \n" );
	mat1 =	cargar(mat1,nFil1,mCol1);
	printf("----\n");
	mostrar(mat1,nFil1,mCol1);
	printf("----\n");  

	printf( "Ingrese el numero de filas de la Segunda Matriz: " );
	scanf("%d", & nFil2);
	printf( "Ingrese el Numero de columnas de la Segunda Matriz : " );
	scanf("%d", & mCol2);
	mat2 = matrizInicializar(mat2,nFil2,mCol2);
	
	printf( "Carga de los elementos de la Segunda Matriz : \n" );
	mat2 =  cargar(mat2,nFil2,mCol2);
	printf("----\n");
	mostrar(mat2,nFil2,mCol2);
	printf("----\n");

	if (mCol1 == nFil2){ /*Condicion necesaria para efectuar el producto cruz*/
		printf( "El producto Cruz  de la las dos matrices es : \n" );	
		int** result = productoCruz(mat1,mat2,nFil1,mCol1,mCol2);
		printf("----\n");
		mostrar(result,nFil1,mCol2);
		printf("----\n");
		free(mat1);/*Libera el espacio reservado para mat1*/
		free(mat2);	/*Libera el espacio reservado para mat2*/
    free(result);	/*Libera el espacio reservado para result*/	
	}else{
		printf(" El producto no se puede efectuar por que el numero de columnas de la primer matriz es diferente del numero de filas de la segunda matriz \n ");	
		free(mat1);/*Libera el espacio reservado para mat1*/
		free(mat2);	/*Libera el espacio reservado para mat2*/
    return 1;
		}		
		
	return 0;
		
}/*FIN DEL CUERPO DEL PROGRAMA*/
